/*
 * Copyright © 2004-2014 chenYuan. All rights reserved.
 * @Website:wwww.jspx.net
 * @Mail:39793751@qq.com
 * @author: chenYuan , 陈原
 * @License: Jspx.net Framework Code is open source (LGPL)，Jspx.net Framework 使用LGPL 开源授权协议发布。
 * @jvm:jdk1.6+  x86/amd64
 *
 */
package com.jspx.sober.util;

import com.jspx.sober.transaction.TransactionManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.jspx.datasource.ConnectionProxy;
import com.jspx.sober.SoberEnv;
import com.jspx.sober.TableModels;
import com.jspx.sober.config.SoberColumn;
import com.jspx.sober.dialect.Dialect;
import com.jspx.sober.dialect.GeneralDialect;
import com.jspx.txweb.IRole;
import com.jspx.utils.*;
import static java.lang.System.arraycopy;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.sql.*;
import java.util.*;
import java.io.Serializable;

/**
 * Created by IntelliJ IDEA.
 * User:chenYuan (mail:39793751@qq.com)
 * Date: 2007-1-6
 * Time: 18:09:10
 */
public abstract class JdbcUtil {
    final static private Logger log = LoggerFactory.getLogger(JdbcUtil.class);

    public static Object[] appendArray(Object[] array, Object append) {
        if (array == null) {
            array = new Object[1];
            array[0] = append;
            return array;
        }
        Object[] result = new Object[array.length + 1];
        arraycopy(array, 0, result, 0, array.length);
        result[array.length] = append;
        return result;
    }

    public static Object[] appendArray(Object[] array, Object[] append) {
        if (array == null) {
            return append;
        }
        if (append == null) {
            return array;
        }
        int length = array.length + append.length;
        Object[] result = new Object[length];
        arraycopy(array, 0, result, 0, array.length);
        arraycopy(append, array.length - array.length, result, array.length, length - array.length);
        return result;
    }

    /**
     *
     *
     * @param stmt 关闭查询器
     */
    public static void closeStatement(Statement stmt) {
        if (stmt != null) try {
            stmt.clearBatch();
            stmt.clearWarnings();
            stmt.close();
        } catch (SQLException ex) {
            log.warn("Could not close JDBC Statement", ex);
        }
    }

    /**
     *
     *
     * @param rs 关闭返回集合
     */
    public static void closeResultSet(ResultSet rs) {
        if (rs != null) try {
            rs.close();
        } catch (Exception ex) {
            log.warn("Could not close JDBC ResultSet", ex);
        }
    }

    /**
     *
     *
     * @param connection 关闭连接
     */
    public static void closeConnection(Connection connection) {
        closeConnection(connection, false);
    }

    /**
     * @param conn  关闭连接
     */
    public static void closeConnection(Connection conn, boolean force) {
        if (conn == null) return;
        try {
            if (force)
            {
                if (conn instanceof ConnectionProxy)
                {
                    ConnectionProxy connectionProxy = ((ConnectionProxy) conn);
                    connectionProxy.release();
                }
            } else
            {
                if (!TransactionManager.getInstance().containsKey(conn.hashCode()))
                    conn.close();
            }
        } catch (Exception e) {
            try {
                conn.close();
            } catch (SQLException e1) {
                //...
            }
        }
    }

    /**
     *
     *
     * @param soberTable 排序表
     * @param field 字段
     * @return 判断在数据库里边是否需要引号
     */
    public static boolean isQuote(TableModels soberTable, Serializable field) {
        return isQuote(soberTable, (String) field);
    }

    /**
     *
     *
     * @param soberTable 排序表
     * @param field 字段
     * @return 判断在数据库里边是否需要引号
     */
    public static boolean isQuote(TableModels soberTable, String field) {
        return soberTable == null || isQuote(soberTable.getColumns(), field);
    }

    /**
     *
     * @param soberColumns 字段
     * @param field 字段
     * @return 字段是否引用
     */
    public static boolean isQuote(List<SoberColumn> soberColumns, String field) {
        if (soberColumns == null || soberColumns.isEmpty()) return true;
        for (SoberColumn column : soberColumns) {
            if (column.getName().equalsIgnoreCase(field)) {
                return !ClassUtil.isNumberType(column.getClassType()) && !column.getClassType().getName().contains("bool")&& !column.getClassType().getName().contains("int")&& !column.getClassType().getName().contains("long");
            }
        }
        return true;
    }

    /**
     *
     *
     * @param resultSet  返回结果
     * @return Map<String,ColumnType> 得到字段信息
     */
    public static Map<String, SoberColumn> getFieldType(final ResultSet resultSet) {
        Map<String, SoberColumn> result = new HashMap<String, SoberColumn>();
        try {
            ResultSetMetaData rsm = resultSet.getMetaData();
            for (int i = 1; i <= rsm.getColumnCount(); i++) {
                SoberColumn soberColumn = new SoberColumn();
                soberColumn.setName(rsm.getColumnName(i));
                result.put(soberColumn.getName(), soberColumn);
            }
        } catch (SQLException e) {
            e.printStackTrace();
            return new HashMap<String, SoberColumn>();
        }
        return result;
    }


    /**
     *
     *
     * @param con 连接
     * @return String 得到数据库名
     * @throws SQLException 连接错误
     */
    public static String getDatabaseName(Connection con) throws SQLException {
        DatabaseMetaData metaData = con.getMetaData();
        String dbName = metaData.getDatabaseProductName().toLowerCase();
        String driverName = metaData.getDriverName().toLowerCase();

        if (driverName.contains("oracle")) {
            return SoberEnv.ORACLE;
        }
        if (driverName.contains("postgresql") || dbName.contains("pql") || dbName.contains("pgql")) {
            return SoberEnv.POSTGRESQL;
        }
        if (driverName.contains("interbase") || dbName.contains("interbase")) {
            return SoberEnv.INTERBASE;
        }
        if (driverName.contains("sqlserver") || driverName.contains("sql server")) {
            return SoberEnv.MSSQL;
        }
        if (driverName.contains("mysql") || dbName.contains("mysql")) {
            return SoberEnv.MYSQL;
        }
        if (driverName.contains("db2") || dbName.contains("db2")) {
            return SoberEnv.DB2;
        }
        if (driverName.contains("firebird") || dbName.contains("firebird")) {
            return SoberEnv.Firebird;
        }
        if (driverName.contains("sqlite")) {
            return SoberEnv.Sqlite;
        }
        if (driverName.contains("smalldb") || dbName.contains("smalldb") || dbName.contains("smallsql")) {
            return SoberEnv.Smalldb;
        }
        return SoberEnv.General;
    }

    /**
     * request 从参数传入Bean对象  MultipartRequest HttpServletRequest 两种情况
     *
     * @param request 请求
     * @param cla     类
     * @return 实体bean
     * @throws Exception 错误
     */
    public static Object getBean(ResultSet request, Class cla, boolean jumpNull, Dialect dialect) throws Exception {
        if (dialect == null) dialect = new GeneralDialect();
        Object result = ClassUtil.newInstance(cla.getName());
        Method[] methods = ClassUtil.getDeclaredSetMethods(cla);

        for (Method method : methods) {
            String propertyName = method.getName();
            if (StringUtil.isNULL(propertyName) || propertyName.startsWith("get") || propertyName.startsWith("is")) {
                continue;
            }
            if (propertyName.startsWith("set") && propertyName.length() > 1) {
                propertyName = StringUtil.uncapitalize(propertyName.substring(3, propertyName.length()));
            }

            Type[] type = method.getParameterTypes();
            if (type != null && type.length > 0) {
                Object value = null;
                try {
                    value = dialect.getResultSetValue(request, propertyName);
                } catch (Exception e) {
                    log.error("错误的字段getResultSetValue:" + propertyName,e);
                }
                if (!(type[0] == IRole.class || jumpNull && ((type[0] == String.class && value == null) || ClassUtil.isNumberType(type[0]) && ObjectUtil.toInt(value) == 0))) {
                    if (value == null) {
                        if (type[0] == java.util.Date.class) value = DateUtil.empty;
                        if (ClassUtil.isNumberType(type[0])) {
                            if (type[0] == int.class || type[0] == long.class) value = 0;
                            else
                                value = StringUtil.empty;
                        }
                    }
                    BeanUtil.setSimpleProperty(result, method.getName(), value);
                }
            }
        }
        return result;
    }
}